/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package Algoritmo;

import Configuracion.Propiedades;
import Controlador.GestorInterseccion;
import Controlador.GestorVelocidad;
import Modelo.DatosIntervalo;
import Modelo.Interseccion;
import Modelo.Universo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Properties;
import java.util.StringTokenizer;

/**
 *
 * @author javier
 */
public class Voraz extends Algoritmo {
    
    ArrayList<Gen> individuoInicial;
    GestorInterseccion intersecciones = GestorInterseccion.getInstance();
    ArrayList<Gen> IndividuoOptimo;
    
    Properties propiedades = new Propiedades().getProperties();
    DatosIntervalo[] intervalos = new DatosIntervalo[17];
    
    public Voraz(Interseccion[][] zona){
        //Seteamos intervalos de fase
        llenarDatosIntervalo(intervalos);
    }
    
    public void run(){
        int z = EvaluacionFuncionObjetivoUsandoMatriz(intersecciones.getMatriz());
        System.out.println("Funcion Z: " + z);
    }
    
    protected int/*Z*/ EvaluacionFuncionObjetivoUsandoMatriz(Interseccion[][] matriz) {
        
        int zTotal = 0;
        //Actualizamos la configuracion por interseccion

        for(int i = 0;i<matriz.length;i++){
            for(int j = 0;j<matriz[i].length;j++){
                
                if(matriz[i][j]!=null){
                    //Se le entrega toda la matriz para tener en cuenta interseciones aledañas
                    int config = obtenerConfiguracion(matriz,i,j);
                    matriz[i][j].setConfiguracion(config);

                    //Ahora calculamos la funcion objetivo

                    if(config !=0){
                        int tiempoTotalHor=Universo.GetInstance().GetTiempoIntervalHorizontal(matriz[i][j].getConfiguracion());
                        int tiempoTotalVer=Universo.GetInstance().GetTiempoIntervalVertical(matriz[i][j].getConfiguracion());
                    

                        int velocidadLimiteHor = obtenerVelocidadLimiteHor(matriz[i][j].getPosX(),matriz[i][j].getPosY());
                        int velocidadLimiteVer = obtenerVelocidadLimiteVer(matriz[i][j].getPosX(),matriz[i][j].getPosY());

                        int totalAutosHor = matriz[i][j].getnAutosEste() + matriz[i][j].getnAutosOeste();
                        int totalAutosVer = matriz[i][j].getnAutosSur() + matriz[i][j].getnAutosNorte();

                        //Distancia recorrida = velocidadLimiteHor * tiempoTotalHor * numVehiculosHor

                        int zHor= velocidadLimiteHor*tiempoTotalHor*totalAutosHor;
                        //Para Intersecciones aledañas
                        zHor+=0;//FALTA
                        int zVer= velocidadLimiteVer*tiempoTotalVer*totalAutosVer;
                        //Para Intersecciones aledañas
                        zVer+=0;//FALTA

                        zTotal += zHor + zVer;
                        
                    }
                }
            }
        }
        return zTotal;
    }

    /* Edgard: Obtiene la configuracion para una interseccion */
    private int obtenerConfiguracion(Interseccion[][] matriz,int i,int j){
        
        //Calculamos Proporciones Horizontal vs Vertical
        
        int numVehiculosHor = matriz[i][j].getnAutosEste()+matriz[i][j].getnAutosOeste();
        int numVehiculosVer = matriz[i][j].getnAutosNorte()+matriz[i][j].getnAutosSur();
        
        int velocidadLimiteHor = obtenerVelocidadLimiteHor(matriz[i][j].getPosX(),matriz[i][j].getPosY());
        int velocidadLimiteVer = obtenerVelocidadLimiteVer(matriz[i][j].getPosX(),matriz[i][j].getPosY());
        
        int velHor = numVehiculosHor * velocidadLimiteHor;
        int velVer = numVehiculosVer * velocidadLimiteVer;
        
        //FALTA tomar en cuenta intersecciones aledañas
        
        return calcularConfiguracion(velHor, velVer);
    }
    
    private void llenarDatosIntervalo(DatosIntervalo[] intervalos){

        File archivo = null;
        FileReader fr = null;
        BufferedReader br = null;
        
        try {

            archivo = new File (propiedades.getProperty("pathDatosIntervalos"));
            fr = new FileReader (archivo);
            br = new BufferedReader(fr);

            String linea;

            for(int i = 0;i<16;i++){
                linea=br.readLine();

                //System.out.println("Datos intevalo: "+linea);
                
                StringTokenizer st = new StringTokenizer (linea);

                int idIntervalo= Integer.parseInt(st.nextToken());
                double interInicial= Double.parseDouble(st.nextToken());
                double interFinal= Double.parseDouble(st.nextToken());
                
                DatosIntervalo di = new DatosIntervalo(idIntervalo, interInicial, interFinal);
                intervalos[i+1]=di;
                    
            }       
               
        } catch (Exception e) {
            
        }
    }
    
    private int calcularConfiguracion(int velHor, int velVer){
        
        double proporcion = 0;
        int config = 0;
        //Encontrar configuracion segun la proporcions en DatosIntervalo
        
        //CONTENIDO DE datosIntervalo.txt UBICACION OBTENIDA DE: datos.properties
        /*
4	0.00	0.25
3	0.25	0.33
2	0.33	0.50
8	0.50	0.50
7	0.50	0.67
12	0.67	0.75
1	0.75	1.00
6	1.00	1.00
11	1.00	1.00
16	1.00	1.00
15	1.00	1.33
10	1.33	1.50
5	1.50	2.00
14	2.00	2.00
9	2.00	3.00
13	3.00	4.00
        */
        //Validar DIV 0
        if(velVer ==0){
            config=4;//30 120
        }
        else{
            proporcion = velHor/velVer;
            if(proporcion>4){
                    config=13;//120 30
            }
            else{
                for(int i = 1;i<17;i++){
                    if(intervalos[i].getIntervaloInicial() <= proporcion && intervalos[i].getIntervaloFinal()>proporcion){
                        config=intervalos[i].getConfiguracion();
                    }
                }
            }
        }

        return config;
    }
}
